package com.scu.qingshi.facade.domain.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.json.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.scu.qingshi.common.enums.ResponseCodeEnum;
import com.scu.qingshi.common.response.BaseResponse;
import com.scu.qingshi.config.cummunity.CommunityFactory;
import com.scu.qingshi.domain.announcement.enums.NoticeTypeEnum;
import com.scu.qingshi.domain.announcement.param.CreateNoticeRequest;
import com.scu.qingshi.domain.authorize.model.AuthorizationEmailMessage;
import com.scu.qingshi.domain.interview.event.AuditSuccessEvent;
import com.scu.qingshi.domain.interview.param.*;
import com.scu.qingshi.domain.interview.service.InterviewDomainService;
import com.scu.qingshi.infrastructure.dao.po.Announcement;
import com.scu.qingshi.infrastructure.dao.po.User;
import com.scu.qingshi.infrastructure.dao.service.AnnouncementService;
import com.scu.qingshi.infrastructure.dao.service.UserService;
import com.scu.qingshi.infrastructure.event.EventBusCenter;
import com.scu.qingshi.facade.domain.InteractionFacade;
import com.scu.qingshi.infrastructure.utils.EmailUtil;
import com.scu.qingshi.ws.CommunityWebSocketServer;
import com.scu.qingshi.ws.UserWebSocketServer;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.checkerframework.checker.units.qual.A;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.validation.Valid;
import java.io.IOException;
import java.util.List;
import java.util.Objects;

/**
 * @author qingshi
 */
@Api(tags = "交互")
@RequestMapping("/interaction")
@RestController
public class InteractionFacadeImpl implements InteractionFacade {

    private final Logger logger = LogManager.getLogger(this.getClass());

    @Autowired
    InterviewDomainService interviewDomainService;

    @Autowired
    EventBusCenter eventBusCenter;

    @Autowired
    AnnouncementService announcementService;

    @Autowired
    UserService userService;

    @Autowired
    EmailUtil emailUtil;

    @ApiOperation("申请参加面试")
    @PostMapping("/apply")
    @Override
    public BaseResponse applyForProcess(ApplyRequest request) throws Exception {

        logger.info("ApplyRequest = {}", request);

        BaseResponse res = new BaseResponse();

        String openId = interviewDomainService.apply(request);

        JSONObject communityObject = new JSONObject();
        communityObject.putOnce("type","apply");
        communityObject.putOnce("data","有新的面试申请");
        CommunityWebSocketServer.sendInfo(communityObject.toString(),openId);
        JSONObject userObject = new JSONObject();
        userObject.putOnce("type","applySuccess");
        userObject.putOnce("data","提交成功");
        UserWebSocketServer.sendInfo(userObject.toString(), String.valueOf(request.getUserId()));

        res.setMsg("申请已发送");
        res.setCode(ResponseCodeEnum.SUCCESS.name());
        res.setSuccess(true);
        return res;
    }

    @ApiOperation("是否通过此轮面试")
    @PostMapping("/judge")
    @Override
    public BaseResponse judge(JudgeRequest req) throws Exception {
        logger.info("JudgeRequest = {}",req);
        BaseResponse res = new BaseResponse();
        boolean success = interviewDomainService.judge(req);

        JSONObject object = new JSONObject();
        object.putOnce("type","judge");
        object.putOnce("data",req.getSuccess()?"恭喜您已经通过面试:"+req.getInterName():"很遗憾您没有通过面试:"+req.getInterName());
        // 实时通知在线用户面试结果
        UserWebSocketServer.sendInfo(
                object.toString(),
                String.valueOf(req.getUserId()));

        // 面试完成
        if (success){
            JSONObject notice = new JSONObject();
            notice.putOnce("type","success");
            notice.putOnce("data","恭喜您已经通过所有面试，请留意社团的邀请");
            UserWebSocketServer.sendInfo(
                    notice.toString(),
                    String.valueOf(req.getUserId())
            );
        }

        res.setMsg("判决成功");
        res.setCode(ResponseCodeEnum.SUCCESS.name());
        res.setSuccess(true);
        return res;
    }

    @ApiOperation("记录面试评述")
    @PostMapping("/record")
    @Override
    public BaseResponse record(RecordReviewRequest request) throws Exception {

        logger.info("技术面试评述, RecordReviewRequest = {}", request);
        BaseResponse res = new BaseResponse();

        interviewDomainService.record(request);

        JSONObject object = new JSONObject();
        object.putOnce("type","record");
        object.putOnce("data","记录成功");
        CommunityWebSocketServer.sendInfo(object.toString(),request.getOpenId());

        res.setMsg("记录成功");
        res.setCode(ResponseCodeEnum.SUCCESS.name());
        res.setSuccess(true);
        return res;
    }

    @ApiOperation("审核参加面试申请")
    @PostMapping("/audit")
    @Override
    public BaseResponse audit(@Valid AuditRequest req) throws Exception{

        BaseResponse res = new BaseResponse();

        interviewDomainService.audit(req);

        JSONObject object = new JSONObject();
        object.putOnce("type","audit");
        object.putOnce("data","社团:["+ CommunityFactory.getCommunity(req.getOpenId()).getName()+"]已经审核了你的面试申请");
        // 如果用户在线，则实时通知用户已审核
        UserWebSocketServer.sendInfo(
                object.toString()
                ,String.valueOf(req.getUserId()));

        // 发布 [审核成功事件 AuditSuccessEvent]
        //     [监听后，通过邮箱通知审核结果，并提醒参加面试]
        // 通过异步来优化性能
        eventBusCenter.postEvent(AuditSuccessEvent.builder()
                .auditResult(req.getAuditResult())
                .userId(req.getUserId())
                .openId(req.getOpenId())
                .interId(req.getInterId())
                .build());


        res.setMsg("审核成功");
        res.setCode(ResponseCodeEnum.SUCCESS.name());
        res.setSuccess(true);
        return res;
    }

    @ApiOperation(value = "是否加入社团")
    @PostMapping("/isJoin")
    @Override
    public BaseResponse isJoin(@ApiParam(required = true,value = "加入请求") JoinRequest req) {

        logger.info("JoinRequest = {}",req);

        User user = userService.getById(req.getUserId());
        if (req.getIsJoin()){
            user.join(req.getOpenId());
            userService.iUpdate(user);
            emailUtil.sendEmail(AuthorizationEmailMessage.FROM,
                    CommunityFactory.getCommunity(req.getOpenId()).getEmail(),
                    "新的成员加入提醒",
                    "用户:"+user.toString()+",已同意加入社团");
        }
        else {
            emailUtil.sendEmail(AuthorizationEmailMessage.FROM,
                    CommunityFactory.getCommunity(req.getOpenId()).getEmail(),
                    "新的成员加入提醒",
                    "用户:"+user.toString()+",拒绝加入社团");

        }

        Announcement announcement = announcementService.getById(req.getNoticeId());
        announcement.setEffective(0);
        announcementService.updateById(announcement);

        BaseResponse res = new BaseResponse();
        res.setMsg("操作成功");
        res.setCode(ResponseCodeEnum.SUCCESS.name());
        res.setSuccess(true);
        return res;
    }

    @ApiOperation(value = "发送公告")
    @PostMapping("/publishNotice")
    public BaseResponse publishNotice(CreateNoticeRequest req){

        logger.info("CreateNoticeRequest = {}",req);

        Announcement announcement = new Announcement();
        announcement.setContent(req.getContent());
        announcement.setOpenId(req.getOpenId());
        announcement.setType(req.getType());
        announcement.setExpireTime(DateUtil.nextMonth().toJdkDate());
        announcementService.save(announcement);
        if (Objects.equals(req.getType(), NoticeTypeEnum.COMMUNITY_INNER_NOTICE.name())){
            QueryWrapper<User> wrapper = new QueryWrapper<>();
            wrapper.like("open_id",req.getOpenId());
            List<User> users = userService.getBaseMapper().selectList(wrapper);
            String communityEmail = CommunityFactory.getCommunity(req.getOpenId()).getEmail();
            String title = "来自俱乐部 ["+CommunityFactory.getCommunity(req.getOpenId()).getName()+"] 的通告";
            users.forEach(user -> {
                emailUtil.sendEmail(communityEmail,user.getEmail(),title,req.getContent());
            });
        }

        BaseResponse res = new BaseResponse();
        res.setMsg("操作成功");
        res.setCode(ResponseCodeEnum.SUCCESS.name());
        res.setSuccess(true);
        return res;
    }

}
